/**
 * 
 */
package com.bobamrz.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Restrictions;

import com.bobamrz.dao.DocCatalogDAO;
import com.bobamrz.dao.DocTypeHomeExt;
import com.bobamrz.dao.DocumentDAO;
import com.bobamrz.domain.AtrTypeSelectionValue;
import com.bobamrz.domain.DataType;
import com.bobamrz.domain.DocAttribute;
import com.bobamrz.domain.DocAttributeType;
import com.bobamrz.domain.DocCatalog;
import com.bobamrz.domain.DocType;
import com.bobamrz.domain.DocTypeAttribute;
import com.bobamrz.domain.Document;
import com.bobamrz.domain.DocumentDocCatalog;
import com.bobamrz.domain.DocumentDocType;
import com.bobamrz.frontend.DocumentViewServlet;
import com.bobamrz.hibernate.HibernateUtil;

public class DocumentService {
	
	private Logger log = Logger.getLogger(DocumentService.class);

	private DocTypeHomeExt docTypeHome = new DocTypeHomeExt();
	private DocumentDAO documentDAO = new DocumentDAO();
	private DocCatalogDAO docCatalogDAO = new DocCatalogDAO();
	
	public void changeDocumentsCatalog(List<Long> documentIds, Long catalogId) {
		DocCatalog catalog = docCatalogDAO.getById(catalogId);
		catalog.setContentUpdated(new Date());
		
		Set<DocCatalog> catalogs = new HashSet<DocCatalog>();
		catalogs.add(catalog);
		for(Long docId : documentIds) {
			Document document = documentDAO.getById(docId);
			Set<DocumentDocCatalog> oldLinks = document.getDocumentDocCatalogs();
			for(DocumentDocCatalog oldLink : oldLinks) {
				oldLink.setDocCatalog(null);
			}
			document.setDocumentDocCatalogs(null);
			
			Set<DocumentDocCatalog> links = new HashSet<DocumentDocCatalog>();
			DocumentDocCatalog link = new DocumentDocCatalog();
			link.setDocCatalog(catalog);
			link.setDocument(document);
			links.add(link);
			catalog.setDocumentDocCatalogs(links);
			document.setDocumentDocCatalogs(links);
			
			documentDAO.save(document);
		}
		docCatalogDAO.save(catalog);
	}

	public List<Document> getDocumentList(long catalogId) {
		DocCatalog docCatalog = docCatalogDAO.getById(catalogId);
		Set<DocumentDocCatalog> documentDocCatalogs = docCatalog.getDocumentDocCatalogs();
		log.debug("documentDocCatalogs fetched: "+documentDocCatalogs.size());
		List<Document> result = new ArrayList<Document>();
		for(DocumentDocCatalog docCat : documentDocCatalogs) {
			result.add(docCat.getDocument());
		}
		return result;
	}
	
	public List<Document> getDocumentList(List<Long> docIds) {
		List<Document> result = documentDAO.getByIds(docIds);
		return result;
	}
	
	public List<Map<String, Object>> getNewDocumentData(String docTypeName) {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		
		Map<String, Object> commonMap = new TreeMap<String, Object>();
		commonMap.put("dataType", "common");
		commonMap.put("docType", docTypeName);
		commonMap.put("name", "");
		commonMap.put("description", "");
		commonMap.put("filename", "");
		commonMap.put("status", "");
		commonMap.put("id", "new");
		result.add(commonMap);
		
		DocType docType = docTypeHome.findByName(docTypeName);
		
		Set<DocTypeAttribute> docAttributes = docType.getDocTypeAttributes();
		for (DocTypeAttribute attribute : docAttributes) {
			DocAttributeType type = attribute.getDocAttributeType();
			DataType dataType = type.getDataType();

			Map<String, Object> attributeMap = new TreeMap<String, Object>();
			if (dataType.getTypeName().equals("string")) {
				fillTextAttributeMap(type, attributeMap);
			} else if (dataType.getTypeName().equals("number")) {
				fillTextAttributeMap(type, attributeMap);
			} else if (dataType.getTypeName().equals("kuupaev")) {
				fillDateAttributeMap(type, attributeMap);
			} else if (dataType.getTypeName().equals("valik nimekirjast")) {
				fillSelectAttributeMap(type, attributeMap);
			}
			result.add(attributeMap);
		}

		Map<String, Object> attributes = new TreeMap<String, Object>();
		result.add(attributes);
		return result;

	}

	public List<Map<String, Object>> getDocumentData(long documentId) {
		Document document = documentDAO.getById(documentId);
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();

		Map<String, Object> commonMap = fillCommonDataMap(document);
		result.add(commonMap);

		Set<DocAttribute> docAttributes = document.getDocAttributes();
		for (DocAttribute attribute : docAttributes) {
			DocAttributeType docAttributeType = attribute.getDocAttributeType();
			DataType dataType = docAttributeType.getDataType();

			Map<String, Object> attributeMap = new TreeMap<String, Object>();
			if (dataType.getTypeName().equals("string")) {
				fillTextAttributeMap(attribute, docAttributeType, attributeMap);
			} else if (dataType.getTypeName().equals("number")) {
				fillNumberAttributeMap(attribute, docAttributeType, attributeMap);
			} else if (dataType.getTypeName().equals("kuupaev")) {
				fillDateAttributeMap(attribute, docAttributeType, attributeMap);
			} else if (dataType.getTypeName().equals("valik nimekirjast")) {
				fillSelectAttributeMap(attribute, docAttributeType, attributeMap);
			}
			result.add(attributeMap);
		}
		return result;
	}

	private void fillTextAttributeMap(DocAttribute attribute,
			DocAttributeType docAttributeType, Map<String, Object> attributeMap) {
		attributeMap.put("dataType", "attribute");
		attributeMap.put("type", "textfield");
		attributeMap.put("lable", docAttributeType.getTypeName());
		attributeMap.put("value", attribute.getValueText());
	}
	
	private void fillNumberAttributeMap(DocAttribute attribute,
			DocAttributeType docAttributeType, Map<String, Object> attributeMap) {
		attributeMap.put("dataType", "attribute");
		attributeMap.put("type", "textfield");
		attributeMap.put("lable", docAttributeType.getTypeName());
		attributeMap.put("value", attribute.getValueNumber().toString());
	}
	
	private void fillDateAttributeMap(DocAttribute attribute,
			DocAttributeType docAttributeType, Map<String, Object> attributeMap) {
		attributeMap.put("dataType", "attribute");
		attributeMap.put("type", "date");
		attributeMap.put("lable", docAttributeType.getTypeName());
		attributeMap.put("value", attribute.getValueDate().toString());
	}
	
	private void fillSelectAttributeMap(DocAttribute attribute,
			DocAttributeType docAttributeType, Map<String, Object> attributeMap) {
		attributeMap.put("dataType", "attribute");
		attributeMap.put("type", "select");
		attributeMap.put("lable", docAttributeType.getTypeName());
		attributeMap.put("value", attribute.getAtrTypeSelectionValue().getAtrTypeSelectionValue()+"");
		
		List<Map<String, String>> values = getAvailableSelectValues(docAttributeType);
		attributeMap.put("values", values);
	}

	private List<Map<String, String>> getAvailableSelectValues(DocAttributeType docAttributeType) {
		Set<AtrTypeSelectionValue> selectionValues = docAttributeType.getAtrTypeSelectionValues();
		List<Map<String, String>> values = new ArrayList<Map<String, String>>();
		for (AtrTypeSelectionValue value : selectionValues) {
			Map<String, String> valueMap = new TreeMap<String, String>();
			valueMap.put("value", value.getAtrTypeSelectionValue() + "");
			valueMap.put("text", value.getValueText());
			values.add(valueMap);
		}
		return values;
	}

	private Map<String, Object> fillCommonDataMap(Document document) {
		String docTypeName = document.getDocumentDocType().getDocType().getTypeName();
		Map<String, Object> commonMap = new TreeMap<String, Object>();
		commonMap.put("dataType", "common");
		commonMap.put("id", document.getDocument()+"");
		commonMap.put("name", document.getName());
		commonMap.put("description", document.getDescription());
		commonMap.put("filename", document.getFilename());
		commonMap.put("docType", docTypeName);
		commonMap.put("status", document.getDocStatusType().getDocStatusType()
				+ "");
		return commonMap;
	}

	private void fillTextAttributeMap(DocAttributeType type,
			Map<String, Object> attributeMap) {
		attributeMap.put("dataType", "attribute");
		attributeMap.put("type", "textfield");
		attributeMap.put("lable", type.getTypeName());
		attributeMap.put("value", type.getDefaultValueText());
	}

	private void fillDateAttributeMap(DocAttributeType type,
			Map<String, Object> attributeMap) {
		attributeMap.put("dataType", "attribute");
		attributeMap.put("type", "date");
		attributeMap.put("lable", type.getTypeName());
		attributeMap.put("value", type.getDefaultValueText());
	}

	private void fillSelectAttributeMap(DocAttributeType type,
			Map<String, Object> attributeMap) {
		List<Map<String, String>> values = getAvailableSelectValues(type);

		attributeMap.put("dataType", "attribute");
		attributeMap.put("type", "select");
		attributeMap.put("lable", type.getTypeName());
		attributeMap.put("value", type.getDefaultValueText());
		attributeMap.put("values", values);
	}

	public DocTypeHomeExt getDocTypeHome() {
		return docTypeHome;
	}

	public void setDocTypeHome(DocTypeHomeExt docTypeHome) {
		this.docTypeHome = docTypeHome;
	}

}
